
import urllib2
import rfc822
from xml.dom.minidom import parse, parseString
from xml.parsers.expat import ExpatError

from twisted.internet import reactor
from twisted.python import log
from smap import driver, util

def get_val(dom, key):
    v = dom.getElementsByTagName(key)[0].firstChild.nodeValue
    return v

class WunderGround(driver.SmapDriver):
    def setup(self, opts):
        self.url = opts.get("Address", 
                            "http://api.wunderground.com/weatherstation/WXCurrentObXML.asp")
        self.ids = opts.get("ID", ["KCABERKE28"])
        print self.ids
        self.rate = int(opts.get("Rate", 60))
        self.last_time = 0
        self.metadata_done = False
        
        for self.id in self.ids:
            self.add_timeseries("/" + str(self.id) + "/wind_dir", "deg")
            self.add_timeseries("/" + str(self.id) + "/wind_speed", "m/s", data_type="double")
            self.add_timeseries("/" + str(self.id) + "/wind_gust", "m/s", data_type="double") 
            self.add_timeseries("/" + str(self.id) + "/humidity", "rh")
            self.add_timeseries("/" + str(self.id) + "/temperature", "F", data_type="double") 
            self.add_timeseries("/" + str(self.id) + "/pressure", "mb", data_type="double")   
            self.add_timeseries("/" + str(self.id) + "/dew_point", "F", data_type="double")   

    def start(self):
        util.periodicSequentialCall(self.update).start(self.rate)

    def update(self):
        for self.id in self.ids:
            try:
                url = self.url + "?ID=" + str(self.id)
                print url
                fh = urllib2.urlopen(url, timeout=10)
            except urllib2.URLError, e:
                print "URLError getting reading: [%s]: %s" % (url, str(e))
                log.err("URLError getting reading: [%s]: %s" % (url, str(e)))
                return
            except urllib2.HTTPError, e:
                print "HTTP Error: [%s]: %s" % (url, str(e))
                log.err("HTTP Error: [%s]: %s" % (url, str(e)))
                return
    
            try:
                dom = parse(fh)
            except ExpatError, e:
                print "Exception parsing DOM [%s]: %s" % (url, str(e))
                log.err("Exception parsing DOM [%s]: %s" % (url, str(e)))
                retuSacramentorn
    
            try:
                reading_time = rfc822.parsedate_tz(get_val(dom, "observation_time_rfc822"))
                reading_time = int(rfc822.mktime_tz(reading_time))
            except Exception, e:
                print "Exception finding time [%s]: %s" % (url, str(e))
                log.err("Exception finding time [%s]: %s" % (url, str(e)))
                return
    
            if reading_time > self.last_time:
                self.add("/" + str(self.id) + '/wind_dir', reading_time, int(get_val(dom, "wind_degrees")))
                self.add("/" + str(self.id) + '/wind_speed', reading_time, float(get_val(dom, "wind_mph")))
                self.add("/" + str(self.id) + "/wind_gust", reading_time, float(get_val(dom, "wind_gust_mph")))
                self.add("/" + str(self.id) + "/humidity", reading_time, int(get_val(dom, "relative_humidity").rstrip('%')))
                self.add("/" + str(self.id) + "/temperature", reading_time, float(get_val(dom, "temp_f")))
                self.add("/" + str(self.id) + "/pressure", reading_time, float(get_val(dom, "pressure_mb")))
                self.add("/" + str(self.id) + "/dew_point", reading_time, float(get_val(dom, "dewpoint_f")))
                self.last_time = reading_time
    
            if not self.metadata_done:
                self.metadata_done = True
                self.set_metadata('/', {
                        'Extra/StationType' : get_val(dom, "station_type"),
                        'Extra/StationID' : get_val(dom, "station_id"),
                        'Location/Latitude' : get_val(dom, "latitude"),
                        'Location/Longitude': get_val(dom, "longitude"),
                        'Location/Altitude': get_val(dom, "elevation"),
                        'Location/Uri' : get_val(dom, "link"),
                        'Location/City' : get_val(dom, "city"),
                        'Location/State' : get_val(dom, "state"),
                        })
    
            dom.unlink()
